package Template5::DTD::Base;

use strict;
use warnings;
use overload '==' => \&__compare;

#-------------------------------------------------------------------------------
use Template5::DTD::Element;

#-------------------------------------------------------------------------------
#public constructor
sub new()
{
	my $class     = shift;
	my $namespace = shift;
	my $table     = shift;
	my $import    = shift;

	my $this = {'namespace' => $namespace,
							'table'     => $table,
							'import'    => $import};

	return bless($this, $class);
};

#public
sub get_namespace()
{
	my $this = shift;
	return $this->{'namespace'};
};

#private
sub __compare($)
{
	my $this   = shift;
	my $dtdobj = shift;

	return ref($this) eq ref($dtdobj);
};

#protected virtual
sub _in_namespace($)
{
	my $this    = shift;
	my $nameurl = shift;
	my $nsurl   = $this->{'namespace'};

	return $nameurl =~ /^$nsurl([^\\\/#]+)$/
};

#private
sub __element_create($)
{
	my $this    = shift;
	my $nameurl = shift;

	my $retVal = undef; 
	my $nsurl = $this->{'namespace'};

	if($this->_in_namespace($nameurl))
	{
		my $localname = substr($nameurl, length($nsurl));
		
		foreach my $existslocalname(keys(%{$this->{'table'}}))
		{
			my $allowedindex = $existslocalname;		
			$existslocalname = ($existslocalname eq '::')?$localname:$existslocalname;

			if($existslocalname eq $localname)
			{
				$retVal = Template5::DTD::Element->new($this, $localname, $this->{'table'}->{$allowedindex});
				last;
			};
		};
	}
	else
	{
		foreach my $prefix (keys(%{$this->{'import'}}))
		{
			my $dtd = $this->{'import'}->{$prefix};   
			my $dtdElm = $dtd->element_create($nameurl);
           
			if(defined($dtdElm))
			{
				$retVal = $dtdElm;
				last;
			};
		};
	};

	return $retVal;
};

#public
sub element_create($)
{
	my $this = shift;
	my $nameurl = shift;
	
	my $retVal = undef;
	$nameurl = $nameurl?$nameurl:'';
	
	if($nameurl ne $this->{'namespace'})
	{	
  	$retVal = $this->__element_create($nameurl);  	
	}
	else
	{
		$retVal = Template5::DTD::Element->new($this, '', $this->{'table'}->{''});
	};

	return $retVal;
};

#public
sub element_localname($)
{
	my $this    = shift;
	my $hDTDElm = shift;

	my $retVal = undef;
	
	if($hDTDElm->{'dtd'} == $this)
	{
		$retVal = $hDTDElm->{'localname'};
	}
	else
	{		
		foreach my $prefix (keys(%{$this->{'import'}}))
		{
			my $dtd = $this->{'import'}->{$prefix};
			my $localname = $dtd->element_localname($hDTDElm);
			
			if(defined($localname))
			{
				$retVal = sprintf(($localname ne '')?'%s::%s':'%s', $prefix, $localname);
				last;
			};
		};	
	};

	return $retVal;
};

#public
sub element_exists($)
{
	my $this = shift;
	my $hDTDElm = shift;
	
	return defined($this->element_localname($hDTDElm));
};

1;

